package com.exchange.aspect.logger;

import com.alibaba.fastjson.JSON;
import com.exchange.dto.LoggerDto;
import com.exchange.user.entity.SysUser;
import com.exchange.logger.LoggerService;
import com.exchange.user.service.SysUserService;
import com.exchange.utils.HttpContextUtil;
import com.exchange.utils.IpUtil;
import com.exchange.utils.result.CommonResult;
import com.exchange.utils.result.ResultCodeEnum;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AnnotationUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Enumeration;

/***
 *                    .::::.
 *                  .::::::::.
 *                 :::::::::::
 *             ..:::::::::::'
 *           '::::::::::::'
 *             .::::::::::
 *        '::::::::::::::..
 *             ..::::::::::::.
 *           ``::::::::::::::::
 *            ::::``:::::::::'        .:::.
 *           ::::'   ':::::'       .::::::::.
 *         .::::'      ::::     .:::::::'::::.
 *        .:::'       :::::  .:::::::::' ':::::.
 *       .::'        :::::.:::::::::'      ':::::.
 *      .::'         ::::::::::::::'         ``::::.
 *  ...:::           ::::::::::::'              ``::.
 * ```` ':.          ':::::::::'                  ::::..
 *                    '.:::::'                    ':'````..
 *
 * @Author liuhai
 * @Date 2020-10-04 15:33:45
 * @Description 日志记录切面
 */
@Configuration
@Aspect
public class LoggerAspect {

    @Resource
    private LoggerService loggerService;
    @Resource
    private SysUserService userService;

    @Pointcut("@annotation(com.exchange.aspect.logger.SysLogger)")
    public void pointcut() {    }

    @Around(value = "pointcut()")
    public CommonResult addLog(ProceedingJoinPoint joinPoint) throws Exception{
        LoggerDto loggerDto = new LoggerDto();
        Object proceed = null;
        long startTime = System.currentTimeMillis();
        try {
            Signature sig = joinPoint.getSignature();
            if (!(sig instanceof MethodSignature)) {
                throw new IllegalArgumentException("该注解只能用于方法");
            }
            MethodSignature msig = (MethodSignature) sig;
            Object target = joinPoint.getTarget();

            String className = target.getClass().getName();
            Method method = target.getClass().getMethod(msig.getName(), msig.getParameterTypes());

            String handlerInfo = className + "#" + method.getName();

            SysLogger sysLogger = AnnotationUtils.findAnnotation(method, SysLogger.class);

            HttpServletRequest request = HttpContextUtil.getHttpServletRequest();
            Enumeration<String> headNames = request.getHeaderNames();

            // 获取用户token
            String userToken = "";
            String headName = null;
            while(headNames.hasMoreElements()){
                headName = headNames.nextElement();
                if("user_token".equals(headName)){
                    userToken = request.getHeader(headName);
                }
            }

            if(!"".equals(userToken)){
                // 根据token获取用户信息
                SysUser user = userService.getUserByToken(userToken);
                if(null != user){
                    loggerDto.setUserId(user.getUserId().toString());
                    loggerDto.setUserName(user.getUserName());
                }
            }

            loggerDto.setReqURL(request.getRequestURI());
            loggerDto.setIp(IpUtil.getIpAddr(request));
            loggerDto.setDesc(sysLogger.desc());
            loggerDto.setLoggerType(sysLogger.type());
            loggerDto.setMethod(handlerInfo);
            loggerDto.setReqTime(new Date());
            //请求参数
            loggerDto.setParams(JSON.toJSONString(joinPoint.getArgs()));

            //返回结果
            proceed = joinPoint.proceed();

            return (CommonResult)proceed;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            loggerDto.setRestCode(ResultCodeEnum.ERROR.getCode());
            String throwableMessage = throwable.getMessage();
            loggerDto.setMsg(throwableMessage);
            throw new Exception(throwable);
        } finally {
            long duration = System.currentTimeMillis() - startTime;
            loggerDto.setDuration(duration);
            loggerDto.setRest(JSON.toJSONString(proceed));
            loggerService.addMgLogger(loggerDto);
        }
    }


}
